#pragma once

#include <cstddef>
#include <type_traits>
#include <utility>

namespace minidb
{

// note: importance!!!
// Wraps an instance whose destructor is never called.
//
// This is intended for use with function-level static variables. // 用于函数级别的静态变量
template <typename InstanceType>
class NoDestructor
{
public:
    // note: 1、检查内存对齐要求、检查内存布局要求
    //       2、使用成员变量 char[n] 存储对象
    //       3、使用 std::forward 完美转发构造对象，并且使用 placement new 构造对象
    template <typename... ConstructorArgTypes>
    explicit NoDestructor(ConstructorArgTypes &&...args)
    {
        // 检查instance_storage_的大小
        static_assert(sizeof(instance_storage_) >= sizeof(InstanceType),
                      "instance_storage_ is not large enough to hold the instance");
        // 检查布局layout
        static_assert(std::is_standard_layout_v<NoDestructor<InstanceType>>, "");
        // 检查是否内存对齐
        static_assert(offsetof(NoDestructor, instance_storage_) % alignof(InstanceType) == 0,
                      "instance_storage_ does not meet the instance's alignment requirement");
        static_assert(alignof(NoDestructor<InstanceType>) % alignof(InstanceType) == 0,
                      "instance_storage_ does not meet the instance's alignment requirement");
        // !note: placement new + std::forward 构造对象
        new (instance_storage_) InstanceType(std::forward<ConstructorArgTypes>(args)...);
    }

    NoDestructor(const NoDestructor &) = delete;
    NoDestructor &operator=(const NoDestructor &) = delete;

    NoDestructor(NoDestructor &&) = delete;
    NoDestructor &operator=(NoDestructor &&) = delete;

    ~NoDestructor() = default;

    InstanceType *get()
    {
        return reinterpret_cast<InstanceType *>(&instance_storage_);
    }

private:
    // !note:保持 instance_storage_ 的内存对齐与 InstanceType 一致。内存不一致可能导致replacement new出现UB（未定义行为）
    alignas(InstanceType) char instance_storage_[sizeof(InstanceType)]; 
};
} // namespace minidb
